﻿//Steve Was Here- Testing, Testing

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using LogicGates;
using MipsProject;

namespace MipsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            verifyALUOperations();

            //verifyGates();
            //System.Console.WriteLine();

            //verifyAdvancedGates();
            //System.Console.WriteLine();

            //verifyPlexors();
            //System.Console.WriteLine();
            //verifySingleBitALU();

            //verifyXBitAlu(4);
        }

        static void verifyALUOperations()
        {
            int ALU_SIZE = 32;
            // Test ALU operations
            // Inputs: OP CODE, 32-bit INPUT1, 32-bit INPUT2
            // Output: 1 32-bit result
            int input1 = 100, input2 = 32;
            int result;
            ALU alu = new ALU(ALU_SIZE);


            System.Console.WriteLine("{0}-Bit ALU Test", ALU_SIZE);
            // Testing AND operations
            result = alu.Execute(OpCode.AND, input1, input2);
            System.Console.WriteLine("Output of {1} AND {2} = {0}", result, input1, input2);

            // Testing OR operations
            result = alu.Execute(OpCode.OR, input1, input2);
            System.Console.WriteLine("Output of {1} OR {2} = {0}", result, input1, input2);

            // Testing ADD operations
            result = alu.Execute(OpCode.ADD, input1, input2);
            System.Console.WriteLine("Output of {1} + {2} = {0}", result, input1, input2);

            // Testing SUB operations
            result = alu.Execute(OpCode.SUB, input1, input2);
            System.Console.WriteLine("Output of {1} - {2} = {0}", result, input1, input2);

            // Testing SLT operations
            result = alu.Execute(OpCode.SLT, input1, input2);
            System.Console.WriteLine("Output of {1} SLT {2} = {0}", result, input1, input2);

            // Testing NOR operations
            result = alu.Execute(OpCode.SLT, input1, input2);
            System.Console.WriteLine("Output of {1} NOR {2} = {0}", result, input1, input2);
        }

        //This will Verify The Addition of X Bit Numbers (numberOfBits)
        //Scenario: A = 1 Decimal
        //          B = 0 to 2^x Decimal
        //Debug Assert Statements will verify Result of the ALU is equal to B + A
        //For the last case Debug Assert will verify that the Result = 0, and CarryOut = 1
        static void verifyXBitAlu(int numberOfBits)
        {
            //Set up Alu X Bits
            AluXBit aluXBit = new AluXBit(numberOfBits);
            bus aBus = new bus(numberOfBits);
            bus bBus = new bus(numberOfBits);

            //Set Up Inputs for an Add Operation
            aluXBit.bInvert = 0;
            aluXBit.carryIn = 0;
            aluXBit.opCode = 2;

            //Default A= 00000001
            aBus.setBus(1);

            System.Console.WriteLine("Addition Test");
            //Test B from 00000000-11111111
            for (int i = 0; i <= Math.Pow(2, numberOfBits)-1; i++)
            {
                bBus.setBus(i);

                aluXBit.A = aBus;
                aluXBit.B = bBus;

                /*System.Console.WriteLine("A={0}, B={1}, Res_Bin={2}, Res_Dec={3} COut={4} Zero={5}, OFlow={6}"
                            , aluXBit.A.ToString(), aluXBit.B.ToString(), aluXBit.result, aluXBit.result.getBusDecimal(), 
                            aluXBit.carryOut, aluXBit.zero, aluXBit.overflow);*/

                System.Console.WriteLine("A={0}({1}), B={2}({3}), Res_Bin={4}, Res_Dec={5} COut={6} Zero={7}, OFlow={8}"
                            , aluXBit.A.ToString(), aluXBit.A.getBusDecimal(), aluXBit.B.ToString(), aluXBit.B.getBusDecimal()
                            , aluXBit.result, aluXBit.result.getBusDecimal(),
                            aluXBit.carryOut, aluXBit.zero, aluXBit.overflow);
            }

            //Set Up Inputs for an Add Operation
            aluXBit.bInvert = 1;
            aluXBit.carryIn = 1;
            aluXBit.opCode = 2;

            //Default A= 00000001
            bBus.setBus(1);

            System.Console.WriteLine();
            System.Console.WriteLine("Subtraction Test");
            //Test B from 00000000-11111111
            for (int i = 0; i <= Math.Pow(2, numberOfBits) - 1; i++)
            {
                aBus.setBus(i);

                aluXBit.A = aBus;
                aluXBit.B = bBus;

                //Need this here to work, will figure out why later on

                /*System.Console.WriteLine("A={0}, B={1}, Res_Bin={2}, Res_Dec={3} COut={4} Zero={5}, OFlow={6}"
                            , aluXBit.A.ToString(), aluXBit.B.ToString(), aluXBit.result, aluXBit.result.getBusDecimal(),
                            aluXBit.carryOut, aluXBit.zero, aluXBit.overflow);
                 */

                System.Console.WriteLine("A={0}({1}), B={2}({3}), Res_Bin={4}, Res_Dec={5} COut={6} Zero={7}, OFlow={8}"
                            , aluXBit.A.ToString(), aluXBit.A.getBusDecimal(), aluXBit.B.ToString(), aluXBit.B.getBusDecimal()
                            , aluXBit.result, aluXBit.result.getBusDecimal(),
                            aluXBit.carryOut, aluXBit.zero, aluXBit.overflow);
            }
        }
       
        static void verifySingleBitALU()
        {
            AluOneBit alu1 = new AluOneBit();
            
            //And Test with One Bit ALU No Bit Invert
            alu1.bInvert = 0;
            alu1.carryIn=0;
            alu1.opCode = 0;

            System.Console.WriteLine("AND Test with Single Bit ALU");
            for (int i = 0; i < 2; i++) //Loop for A
            {
                alu1.A = i;
                for (int j = 0; j < 2; j++)//Loop for B
                {
                    alu1.B = j;
             
                    System.Console.WriteLine("A= {0}, B={1}, bInvert={2}, CarryIn={3}, Opcode={4}, Result= {5}, CarryOut={6}",
                        alu1.A, alu1.B, alu1.bInvert, alu1.carryIn, alu1.opCode, alu1.result, alu1.carryOut);                   
                }
            }
            System.Console.WriteLine();

            //And Test with One Bit ALU B Bit Invert
            alu1.bInvert = 1;
            alu1.carryIn = 0;
            alu1.opCode = 0;

            System.Console.WriteLine("AND Test with Single Bit ALU");
            for (int i = 0; i < 2; i++) //Loop for A
            {
                alu1.A = i;
                for (int j = 0; j < 2; j++)//Loop for B
                {
                    alu1.B = j;

                    System.Console.WriteLine("A= {0}, B={1}, bInvert={2}, CarryIn={3}, Opcode={4}, Result= {5}, CarryOut={6}",
                        alu1.A, alu1.B, alu1.bInvert, alu1.carryIn, alu1.opCode, alu1.result, alu1.carryOut);
                }
            }
            System.Console.WriteLine();

            //Or Test with One Bit ALU with No B Invert
            alu1.bInvert = 0;
            alu1.carryIn = 0;
            alu1.opCode = 1;

            System.Console.WriteLine("OR Test with Single Bit ALU");
            for (int i = 0; i < 2; i++) //Loop for A
            {
                alu1.A = i;
                for (int j = 0; j < 2; j++)//Loop for B
                {
                    alu1.B = j;

                    System.Console.WriteLine("A= {0}, B={1}, bInvert={2}, CarryIn={3}, Opcode={4}, Result= {5}, CarryOut={6}",
                        alu1.A, alu1.B, alu1.bInvert, alu1.carryIn, alu1.opCode, alu1.result, alu1.carryOut);
                }
            }
            System.Console.WriteLine();

            //Or Test with One Bit ALU with  B Invert
            alu1.bInvert = 1;
            alu1.carryIn = 0;
            alu1.opCode = 1;

            System.Console.WriteLine("OR Test with Single Bit ALU");
            for (int i = 0; i < 2; i++) //Loop for A
            {
                alu1.A = i;
                for (int j = 0; j < 2; j++)//Loop for B
                {
                    alu1.B = j;

                    System.Console.WriteLine("A= {0}, B={1}, bInvert={2}, CarryIn={3}, Opcode={4}, Result= {5}, CarryOut={6}",
                        alu1.A, alu1.B, alu1.bInvert, alu1.carryIn, alu1.opCode, alu1.result, alu1.carryOut);
                }
            }
            System.Console.WriteLine();

            //Add Test with One Bit ALU
            alu1.bInvert = 0;
            alu1.carryIn = 0;
            alu1.opCode = 2;
            System.Console.WriteLine("ADD Test with Single Bit ALU");
            for (int i = 0; i < 2; i++) //Loop for A
            {
                alu1.A = i;
                for (int j = 0; j < 2; j++)//Loop for B
                {
                    alu1.B = j;

                    System.Console.WriteLine("A= {0}, B={1}, bInvert={2}, CarryIn={3}, Opcode={4}, Result= {5}, CarryOut={6}",
                    alu1.A, alu1.B, alu1.bInvert, alu1.carryIn, alu1.opCode, alu1.result, alu1.carryOut);
                }
            }
            System.Console.WriteLine();

            //Sub Test with One Bit ALU
            alu1.bInvert = 1;
            alu1.carryIn = 1;
            alu1.opCode = 2;
            System.Console.WriteLine("SUBTRACT Test with Single Bit ALU");
            for (int i = 0; i < 2; i++) //Loop for A
            {
                alu1.A = i;
                for (int j = 0; j < 2; j++)//Loop for B
                {
                    alu1.B = j;
                    System.Console.WriteLine("A= {0}, B={1}, bInvert={2}, CarryIn={3}, Opcode={4}, Result= {5}, CarryOut={6}",
                    alu1.A, alu1.B, alu1.bInvert, alu1.carryIn, alu1.opCode, alu1.result, alu1.carryOut);
                }
            }
            System.Console.WriteLine();
        }

        static void verifyAdvancedGates()
        {
            HalfAdder halfAdder1 = new HalfAdder();
            System.Console.WriteLine("HalfAdder Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    halfAdder1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Sum= {2}, Carry= {3}", halfAdder1.A, halfAdder1.B, halfAdder1.Sum, halfAdder1.Carry);
                }
            }
            System.Console.WriteLine();

            FullAdderSingleBit fullAdder1 = new FullAdderSingleBit();
            System.Console.WriteLine("FullAdderSingleBit Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    for (int k = 0; k <= 1; k++)
                    {
                        fullAdder1.setInputs(i, j, k);
                        System.Console.WriteLine("Input= {0},{1},{2} Sum= {3}, Carry= {4}", fullAdder1.A, fullAdder1.B, fullAdder1.CarryIn, fullAdder1.Sum, fullAdder1.CarryOut);

                    }
                }
            }

        }
        static void verifyGates()
        {
            //And Test
            AndGate and1 = new AndGate();

            System.Console.WriteLine("And Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    and1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Output= {2}", and1.Input1, and1.Input2, and1.Output);
                }
            }

            System.Console.WriteLine("\nNand Gate Test");
            //Nand Test
            NandGate nand1 = new NandGate();
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    nand1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Output= {2}", nand1.Input1, nand1.Input2, nand1.Output);
                }
            }

            //Or Test
            OrGate or1 = new OrGate();
            System.Console.WriteLine("\nOr Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    or1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Output= {2}", or1.Input1, or1.Input2, or1.Output);
                }
            }

            //Nor Test
            NorGate nor1 = new NorGate();
            System.Console.WriteLine("\nNor Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    nor1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Output= {2}", nor1.Input1, nor1.Input2, nor1.Output);
                }
            }

            //Xor Test
            XorGate xor1 = new XorGate();
            System.Console.WriteLine("\nXor Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    xor1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Output= {2}", xor1.Input1, xor1.Input2, xor1.Output);
                }
            }

            //Xor Test
            XnorGate xnor1 = new XnorGate();
            System.Console.WriteLine("\nXnor Gate Test");
            for (int i = 0; i <= 1; i++)
            {
                for (int j = 0; j <= 1; j++)
                {
                    xnor1.setInputs(i, j);
                    System.Console.WriteLine("Input= {0},{1} Output= {2}", xnor1.Input1, xnor1.Input2, xnor1.Output);
                }
            }
        }

        static void verifyPlexors()
        {
            Multiplexor multiplexor1 = new Multiplexor(3);
         
            for (int i = 0; i < 3; i++)
            {
                switch (i)
                {
                    case 0:
                        multiplexor1.setInputs(1, 0, 0);
                        break;
                    case 1:
                        multiplexor1.setInputs(0, 1, 0);
                        break;
                    case 2:
                        multiplexor1.setInputs(0, 0, 1);
                        break;

                }
                multiplexor1.Select = i;
                System.Console.WriteLine("Input= {0}, {1}, {2}, Select={3}, Output={4}",
                                                    multiplexor1.getInput(2),
                                                    multiplexor1.getInput(1),
                                                    multiplexor1.getInput(0),
                                                    multiplexor1.Select,
                                                    multiplexor1.Output);
            }
        }
        
    }
}
